#ifndef RAM_C
#define RAM_C

typedef struct memblock memBlock;

char* RAM;
uint32_t ramSize;
int heapPointer;
int pos = 0;
memBlock* heap;

struct memblock {
	uint32_t size;
	uint32_t address;
	bool free;
	void* nextBlock;
}; 

uint32_t* heapalloc(uint32_t size)
{
	if(heap == (memBlock*)0) {
		heap = (memBlock*)malloc(sizeof(memBlock));
		heap->nextBlock = 0;
	}
	memBlock* region = heap;
	uint32_t freespace = heapPointer;
	while(region->nextBlock != (void*)0) {
		region = (memBlock*)region->nextBlock;
		if(region->free && region->size >= size)
		{
			region->free = false;
			return region->address;	
		}		
		freespace += region->size;
	}
	if(freespace + size > ramSize)
	{
		RAM = realloc(RAM, freespace + size );
	}
	memBlock* nb = (memBlock*)malloc(sizeof(memBlock)); 
	nb->size = size;
	nb->nextBlock = 0;
	nb->free = false;
	nb->address = freespace;
	region->nextBlock = (void*)nb;
	return freespace;
}

void heapfree(uint32_t pointer)
{
	memBlock* region = heap;
	while(region->nextBlock != (memBlock*)0) {
		
		region = region->nextBlock;
		if(region->address <= pointer && region->address + region->size > pointer) {
			region->free = true;
			return;
		}
	}
}

void dumpRam()
{
	FILE* dmp = fopen("viper-ram.img","w");
	fwrite(RAM,1,0xFFFF,dmp);
	fclose(dmp);
}

uint64_t readInt64()
{
	uint64_t i = ((uint64_t*)(RAM + pos))[0];
	pos += 8;
	return i;
}


uint32_t readInt32()
{
	uint32_t i = ((uint32_t*)(RAM + pos))[0];
	pos += 4;
	return i;
}

uint16_t readInt16()
{
	uint16_t i = ((uint16_t*)(RAM + pos))[0];
	pos += 2;
	return i;
}

uint8_t readInt8()
{
	++pos;
	return RAM[pos - 1];
}

#endif
